﻿
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;

namespace SqlExecuteHelper
{
    public delegate void SingleCompletedEventHandler(int threadIndex);
    public delegate void StoppedEventHandler();
    public delegate void CompletedEventHandler();
    public delegate void ProcessEventHandler(int taskIndex, int threadIndex);

    public class MultiThread
    {
        #region "变量"
        /// <summary>
        /// 任务总数
        /// </summary>
        private int taskTotal;
        /// <summary>
        /// 单个线程最大任务数，默认为5个
        /// </summary>
        private int threadMaxTasks = 5;
        /// <summary>
        /// 线程列表
        /// </summary>
        private Thread[] threads;
        /// <summary>
        /// 线程执行状态列表
        /// </summary>
        private bool[] threadState;
        /// <summary>
        /// 线程任务执行位置（任务编号）列表
        /// </summary>
        private int[] threadTaskIndex;

        /// <summary>
        /// 是否总是执行
        /// </summary>
        private bool isAlwaysRunning;

        public AutoResetEvent[] autoEvents;
        #endregion
        /// <summary>
        /// 单个线程执行完一轮任务后触发该事件
        /// </summary>
        public event SingleCompletedEventHandler SingleCompleted;
        /// <summary>
        /// 当停止所有线程任务时触发该事件
        /// </summary>
        public event StoppedEventHandler Stopped;
        /// <summary>
        /// 所有线程执行完一轮任务后触发该事件
        /// </summary>
        public event CompletedEventHandler Completed;
        /// <summary>
        /// 线程启动执行任务时触发该事件
        /// </summary>
        public event ProcessEventHandler Process;

        /// <summary>
        /// 单个线程最大任务数
        /// </summary>
        public int ThreadMaxTasks
        {
            get
            {
                return this.threadMaxTasks;
            }
            set
            {
                this.threadMaxTasks = value;
            }
        }
        /// <summary>
        /// 余下任务数：任务数均摊后，最后一个线程任务数未满额的情况
        /// </summary>
        public int ResidueTaskTotal
        {
            get
            {
                return taskTotal % ThreadMaxTasks;
            }
        }
        /// <summary>
        /// 线程数（根据任务总数和设置的单个线程最大任务数决定开启多少条线程）
        /// </summary>
        public int ThreadTotal
        {
            get
            {
                return taskTotal / ThreadMaxTasks + (taskTotal % ThreadMaxTasks > 0 ? 1 : 0);
            }
        }
        /// <summary>
        /// 初始化多线程实例
        /// </summary>
        /// <param name="taskTotal">任务总数</param>
        public MultiThread(int taskTotal, bool isAlwaysRunning = false)
        {
            this.taskTotal = taskTotal;
            this.isAlwaysRunning = isAlwaysRunning;
        }

        /// <summary>
        /// 线程启动，开始执行任务
        /// </summary>
        public void Start()
        {
            if (threads != null)
            {
                return;
            }
            threadState = new bool[this.ThreadTotal];
            threadTaskIndex = new int[this.ThreadTotal];
            threads = new Thread[this.ThreadTotal];
            autoEvents = new AutoResetEvent[this.ThreadTotal];

            for (int threadIndex = 0; threadIndex <= this.ThreadTotal - 1; threadIndex++)
            {
                int thIndex = threadIndex;
                threadState[thIndex] = false;
                //初始化线程的执行起点位置（任务编号）
                threadTaskIndex[thIndex] = thIndex * this.threadMaxTasks;
                threads[thIndex] = new Thread(delegate() { this.ExecuteTask(thIndex); });
                autoEvents[thIndex] = new AutoResetEvent(false);
                threads[thIndex].Start();
            }
        }

        /// <summary>
        /// 线程停止，结束当前任务
        /// </summary>
        public void Stop()
        {
            if (threads != null)
            {
                for (int threadIndex = 0; threadIndex <= threads.Length - 1; threadIndex++)
                {
                    threads[threadIndex].Abort();
                }
                if (this.Stopped != null)
                {
                    //触发Stopped事件
                    this.Stopped.Invoke();
                }
            }
        }
        /// <summary>
        /// 执行任务
        /// </summary>
        /// <param name="arg">线程编号</param>
        // private void ExecuteTask(object arg)
        private void ExecuteTask(int threadIndex)
        {
            //提取任务并执行
            int taskIndex = this.GetTask(threadIndex);
            while (isAlwaysRunning || taskIndex != 0)
            {
                taskIndex = this.GetTask(threadIndex);
            }

        }
        /// <summary>
        /// 提取任务
        /// </summary>
        /// <param name="threadIndex">线程编号</param>
        /// <returns>返回下一个任务编号</returns>
        private int GetTask(int threadIndex)
        {

            //得到当前线程最后一个任务的编号
            int lastIndex = this.ThreadMaxTasks * (threadIndex + 1);
            //如果最后一个任务的编号大于任务总数
            if (lastIndex > this.taskTotal)
            {
                //取最大任务数
                lastIndex = this.taskTotal;//this.ThreadMaxTasks * threadindex + this.ResidueTaskTotal;
            }
            int taskIndex = default(int);
            int currentTaskIndex = this.threadTaskIndex[threadIndex];
            //如果当前线程目前执行的任务编号小于最后任务的编号
            if (currentTaskIndex < lastIndex)
            {
                //获取下一个任务
                this.threadTaskIndex[threadIndex] = currentTaskIndex + 1;
                taskIndex = this.threadTaskIndex[threadIndex];
                if (this.Process != null)
                {
                    this.Process.Invoke(taskIndex, threadIndex);
                }
            }
            else
            {
                //任务已执行完毕,触发所有线程任务完成事件
                threadState[threadIndex] = true;
                if (threadState.Count(state => state == false) == 0)
                {
                    //如果全部完成
                    if (this.Completed != null)
                    {
                        //触发complete事件
                        this.Completed.Invoke();
                        //重置线程状态
                        for (int i = 0; i <= threadState.Length - 1; i++)
                        {
                            threadState[i] = false;
                        }
                    }
                }
                //如果是一直运行，那么进入下一轮
                if (isAlwaysRunning)
                {
                    if (this.SingleCompleted != null)
                    {
                        //触发SingleCompleted事件
                        this.SingleCompleted.Invoke(threadIndex);
                    }
                    this.threadTaskIndex[threadIndex] = threadIndex * this.threadMaxTasks;
                    taskIndex = this.threadTaskIndex[threadIndex] + 1;
                }
            }
            return taskIndex;


        }
    }
}
